import ENV from '@/common/env'
import Vue from 'vue'
import { isWeiXin, emptyObject } from './helper'
import { error, hideLoading, linkToEasy } from './fun'

import Storage from '@/common/Storage'

const md5 = require('js-md5')

export const getAccessToken = () => Storage.get('access_token')

export const getUserID = () => Storage.get('user_id')

export const getEnv = () => {
  var rt = ''
  // #ifdef APP-PLUS
  rt = 'app'
  // #endif

  // #ifdef MP-WEIXIN
  rt = 'wx_lp'
  // #endif

  // #ifdef MP-TOUTIAO
  rt = 'tt_lp'
  // #endif

  // #ifdef MP-ALIPAY
  rt = 'ali_lp'
  // #endif

  // #ifdef H5
  // 需要考虑是不是普通浏览器
  if (isWeiXin()) {
    rt = 'wx_mp'
  } else {
    rt = 'wap'
  }
  // #endif
  return rt
}

function getSign (params, appKey, appSecret) {
  var sign
  params.timestamp = uni.$dayjs().unix()

  if (typeof params === 'string') {
    sign = paramsStrSort(params, appKey, appSecret)
  } else if (typeof params === 'object') {
    var arr = []
    for (var i in params) {
      arr.push((i + '=' + params[i]))
    }
    sign = paramsStrSort(arr.join('&'), appKey, appSecret)
  }
  params.sign = sign

  return params
}

function paramsStrSort (paramsStr, appKey, appSecret) {
  var url = paramsStr + '&appid=' + appKey
  var urlStr = url.split('&').sort().join('&')
  var newUrl = urlStr + '&secret=' + appSecret
  // console.log(newUrl)
  return md5(newUrl)
}

export class XHR {
  static checkQuick (url, options) {
    const d = new Date()
    if (options.hasOwnProperty('is_tap') && options.is_tap) {
      const tempActInfo = Storage.get('temp_act_info')
      if (tempActInfo && tempActInfo.hasOwnProperty('act') && tempActInfo.hasOwnProperty('time') && tempActInfo.url && tempActInfo.time) {
        // 同一个请求，不能在0.5s内连点两次
        return url === tempActInfo.url && d.getTime() < (tempActInfo.time + 500)
      }
    }
  }

  static formData (param) {
    const _param = emptyObject({ obj: param, clearValues: [null, undefined, '', 'null', 'undefined'] })
    var postData = {
      is_dev: ENV.isDev ? 1 : 0,
      build: ENV.build,
      access_token: getAccessToken(),
      env: getEnv(),
      ..._param
    }

    postData = getSign(postData, ENV.appid, ENV.secret)

    return postData// emptyObject(postData)
  }
}

const hookErrorCode = [1, 20005, 20006, 20007]
/**
 *
 * @param url
 * @param method
 * @param data
 * @param options
 * @param isAddHost 如果为true,则不需要加host
 * @returns {Promise<unknown>}
 */
export const ajax = ({ url, method = 'post', data = {}, options = {}, isAddHost = true, headerExt = {} }) => {
  const {
    tip = '', // loading text
    mask = false,
    // timelen = 2000,
    timeout = 100, // 如果tip参数生效，请求结束后会延迟取消loading,有的请求太快了一闪而过
    errtip = false, // 是否提示错误,尽量让接口自己决定如何展示
    // reqHeader = false, // 是否需要把响应头返回放在resolve里面，一般是有时候登录的时候需要从请求头里拿到token的
    onlyData = false// 是否直接返回data，方便结构赋值
  } = options

  if (tip) {
    uni.showLoading({
      title: tip,
      mask
    })
  }

  // let token
  var header = {
    // 'Authorization': 'Bearer ' + token,
    'content-type': 'application/x-www-form-urlencoded',
    ...headerExt
  }

  var _url = !isAddHost ? url : ENV.apiBaseUrl + url

  // #ifndef H5
  if (isAddHost) _url = ENV.apiBaseHost + _url
  // #endif

  // console.log(`请求链接${_url}`)
  // console.log('请求参数:', data)
  return new Promise((resolve, reject) => {
    uni.request({
      header,
      url: _url,
      method,
      data,
      success: (ret) => {
        const { statusCode, data } = ret
        if (statusCode !== 200 || typeof data !== 'object') {
          error('服务器去旅行了')
          reject(new Error('服务器去旅行了'))
        }
        const { data: res } = ret

        // #ifdef APP-PLUS
        console.log('响应', res)
        // #endif
        // console.log('响应',res)
        const { code = 1, msg = '请求未成功' } = res

        if (hookErrorCode.includes(code)) {
          if (code === 20005) {
            // #ifdef H5
            Storage.set('login_back_url', location.href)
            // #endif
            error(res.msg)
            // 重置用户信息
            setTimeout(() => {
              uni.navigateTo({
                url: '/pages/login'
              })
            }, 500)
            return
          }

          if (code === 20007) {
            error(res.msg)
            // 重置用户信息
            // setTimeout(() => {
            //   uni.navigateTo({
            //     url: '/pages/login'
            //   })
            // }, 500)
            return
          }

          if (code === 20006) {
            error(res.msg)
            linkToEasy('/pages/user/profile?require_back=1')
            // 重置用户信息
            // setTimeout(() => {
            //   uni.navigateTo({
            //     url: '/pages/login'
            //   })
            // }, 500)
            return
          }

          resolve(onlyData ? res.data : res)
        } else {
          // 配置决定是否显示错误提示
          if (errtip) error(msg)
          // if (ENV.isDev) error(msg)
          reject(res)
        }
      },
      fail: (err) => {
        // #ifdef APP-PLUS
        console.log('错误响应', err)
        // #endif
        // 标记为http请求出错，而不是业务逻辑返回的错误
        reject(new Error(err.errMsg))
      },
      complete: () => {
        if (tip) {
          setTimeout(function () {
            hideLoading()
          }, timeout)
        }
      }
    })
  })
}

export const fetch = function ({ param = {}, options = false, url, method = 'post' }) {
  try {
    if (!url) {
      error('url必传')
      throw Error('url必传')
    }

    param.act = url

    if (options && options.hasOwnProperty('method')) {
      method = options.method
    }

    // 自动带city_id
    // if (Storage.get('CURRENT_CITY_ID')) {
    //   param.current_city_id = Storage.get('CURRENT_CITY_ID')
    // }

    // 检查是否同一个接口请求过快
    // if (XHR.checkQuick(url, options)) {
    //   return Promise.reject(new Error('请求过快'))
    // }
    // 签名
    const data = XHR.formData(param)

    // console.log(data)
    return ajax({
      url,
      method,
      data,
      options
    })
  } catch (e) {
    console.log('request error :' + JSON.stringify(e))
    return Promise.reject(e)
  }
}

export const upload = ({ filePath, idx = 0, name = 'funupload', param = {}, progressList = [], url = '/tool/upfile' }) => {
  const _param = {
    access_token: getAccessToken(),
    env: getEnv(),
    channel: getEnv(),
    act: url,
    ...param
  }

  var _url = ENV.apiBaseUrl + url

  // #ifndef H5
  _url = ENV.apiBaseHost + _url
  // #endif

  const formData = XHR.formData(_param)

  console.log(filePath, name, formData)
  return new Promise((resolve, reject) => {
    const uploadTask = uni.uploadFile({
      url: _url,
      filePath,
      name,
      formData,
      success: (res) => {
        // console.log('upload file result', res)
        let { data: body } = res
        if (typeof body === 'string' && body) {
          body = JSON.parse(body)
        }
        //
        // console.log('body is', body)
        if (body.hasOwnProperty('data') && typeof body.data === 'string') {

        } else {
          reject(Error(body.msg))
          return
        }

        const { code = 0, data: path } = body

        if (code === 1 && path) {
          resolve(path)
        } else {
          console.log(res)
          reject(Error(body.msg))
        }
      },
      fail: (err) => {
        reject(err)
      },
      complete: (rt) => {

      }
    })

    uploadTask.onProgressUpdate((res) => {
      console.log('上传进度' + res.progress)
      console.log('已经上传的数据长度' + res.totalBytesSent)
      console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend)

      try {
        Vue.set(progressList, idx, res)
        // progressList[idx] = {...res}
        Storage.set('progress', res)
      } catch (e) {
        console.log('上传进度错误' + e.message)
      }
    })
  })
}

export default {
  ajax
}
